'use client';

import './style.scss';
import { usePathname, useSearchParams } from 'next/navigation';
import { useState, useEffect, useCallback, useRef } from 'react';
import { BoardLayout, BoardSort, PostSearchType } from '@/constants/forum';
import { fetchPostList } from '@/lib/api/forum/board';
import Post from '@/types/forum/post';
import Loading from '@/app/component/Loading';
import Pagination from '@/app/component/Pagination';
import PostListRequest from '@/dtos/request/forum/board/postListRequest';
import BoardResponse from '@/dtos/response/forum/board/boardResponse';
import PostListResponse from '@/dtos/response/forum/board/postListResponse';
import PostWriteButtonfrom from '../_component/PostWriteButton';
import HeaderContent from '../_component/HeaderContent';
import FooterContent from '../_component/FooterContent';
import DefaultListLayout from '../_component/DefaultListLayout';
import AlbumListLayout from '../_component/AlbumListLayout';
import QnAListLayout from '../_component/QnAListLayout';

type ViewProps = {
	_query: {
		page: number;
		perPage: number;
		prefix?: number;
		sort?: BoardSort;
		search: PostSearchType;
		keyword?: string;
	},
	_board: BoardResponse,
	_postList: PostListResponse
};

export default function View({ _query, _board, _postList }: ViewProps)
{
	const pathname = usePathname();
	const searchParams = useSearchParams();

	const [error, setError] = useState<string|null>(null);
	const [loading, setLoading] = useState<boolean>(false);
	const [total, setTotal] = useState<number>(_postList.total);
	const [speaker, setSpeaker] = useState<Post[]>(_postList.speaker);
	const [notice, setNotice] = useState<Post[]>(_postList.notice);
	const [list, setList] = useState<Post[]>(_postList.list);
	const [page, setPage] = useState<number>(_query.page);
	const [perPage, setPerPage] = useState<number>(_query.perPage);
	const [startIndex, setStartIndex] = useState<number>(0);
	const [boardPrefixID, setBoardPrefixID] = useState<number|undefined>(_query.prefix);
	const [sort, setSort] = useState<BoardSort|undefined>(_query.sort);
	const [search, setSearch] = useState<PostSearchType>(_query.search);
	const [keyword, setKeyword] = useState<string|undefined>(_query.keyword);
	const [params, setParams] = useState<Record<string, string>>({});
	const isMounted = useRef(false);

	useEffect(() => {
		if (error) {
			alert(error);
			setError(null);
		}
	}, [error]);

	// 상태 => URL 동기화
	useEffect(() => {
		// 기존 URL 파라미터
		const alreadyParams = new URLSearchParams(searchParams.toString());

		// URL 파라미터 덮어쓰기 및 삭제
		Object.entries(params).forEach(([k, v]) => {
			if (v) {
				alreadyParams.set(k, v);
			} else {
				alreadyParams.delete(k);
			}
		});

		const queryString = `?${alreadyParams.toString()}`;
		if (window.location.search !== queryString) {
			window.history.replaceState(null, '', `${pathname}${queryString}`);
		}

	}, [page, perPage, boardPrefixID, sort, search, keyword]);

	const handleFetchPosts = useCallback(async () => {
		try {
			setLoading(true);

			const res = await fetchPostList({
				boardID: _board.id,
				boardCode: _board.code,
				boardPrefixID: boardPrefixID,
				page,
				perPage,
				sort,
				search,
				keyword
			} as PostListRequest);

			if (!res.data) {
				setError('게시글을 불러올 수 없습니다.');
			} else {
				setTotal(res.data.total);
				setSpeaker(res.data.speaker);
				setNotice(res.data.notice);
				setList(res.data.list);
			}
		} catch (err: any) {
			setError(err.message || '알 수 없는 오류가 발생했습니다.');
		} finally {
			setLoading(false);
		}
	}, [_board.id, _board.code, boardPrefixID, page, perPage, sort, search, keyword]);

	const handleChange = (e: React.ChangeEvent<HTMLSelectElement|HTMLInputElement>) => {
		const { name, value } = e.target;

		let key = '';
		switch (name) {
			case 'boardPrefixID':
				setBoardPrefixID((Number(value) || undefined) as number);
				key = 'prefix';
				break;
			case 'sort':
				setSort(Number(value) as BoardSort);
				break;
			case 'perPage':
				setPerPage(Number(value));
				break;
			case 'search':
				setSearch(Number(value) as PostSearchType);
				break;
			case 'keyword':
				setKeyword(value);
				break;
		}

		if (['sort', 'perPage', 'search', 'keyword'].includes(name)) {
			key = name;
		}

		if (['boardPrefixID', 'perPage', 'search', 'keyword'].includes(name)) {
			handlePageChange(1);
		}

		setParams((prev) => ({ ...prev, [key]: value }));
	};

	const handleSearch = async (e: React.FormEvent) => {
		e.preventDefault();
		handleFetchPosts();
	};

	const handlePageChange = (page: number) => {
		setPage(page);
		setParams((prev) => ({ ...prev, page: String(page) }));
	};

	useEffect(() => {
		if (!isMounted.current) {
			isMounted.current = true;
			return;
		}

		handleFetchPosts();
	}, [page, perPage, boardPrefixID, sort]);

	useEffect(() => {
		setStartIndex(total - ((page - 1) * perPage));
	}, [total, list, page, perPage]);

	return (
		<div id='board'>
			{loading && <Loading />}

			<HeaderContent isEnabled={_board.boardMeta.list.showHeader} content={_board.boardMeta.list.headerContent } />

			<div className='list-header'>
				{/* 말머리 */}
				<section aria-label='말머리 선택'>
					<h1>{ _board.name }</h1>
					<article>
						<ul>
							<li>
								<label {...(!boardPrefixID ? { className: 'active' } : {})}>
									<input type='radio' name='boardPrefixID' value='' checked={boardPrefixID === null} onChange={handleChange} /> 전체
								</label>
							</li>
							{_board.boardPrefix.map((row, i) => (
								<li key={i}>
									<label {...(boardPrefixID === row.id ? { className: 'active' } : {})}
										style={row.color && row.color != '#000000' ? { background: row.color, color: '#f1f1f1' } : undefined}
									>
										<input type='radio' name='boardPrefixID' value={row.id} checked={boardPrefixID === row.id} onChange={handleChange}/>
										{row.name}
									</label>
								</li>
							))}
						</ul>
					</article>
				</section>

				{/* 정렬 */}
				<section aria-label='게시글 정렬'>
					<select name='sort' value={sort ?? ''} title='게시글 정렬' onChange={handleChange}>
						<option value={BoardSort.CreatedAt}>최신순</option>
						<option value={BoardSort.Views}>조회순</option>
						<option value={BoardSort.Comments}>댓글순</option>
						<option value={BoardSort.Likes}>공감순</option>
					</select>
				</section>

				{/* 출력 수 */}
				<section aria-label='게시글 출력 수'>
					<select name='perPage' value={perPage} title='출력 수' onChange={handleChange}>
						<option value='10'>10개씩</option>
						<option value='20'>20개씩</option>
						<option value='30'>30개씩</option>
						<option value='50'>50개씩</option>
						<option value='100'>100개씩</option>
					</select>
				</section>
			</div>

			{/* 게시글 목록 */}
			{(() => {
				switch (_board.boardMeta.list.layout) {
					case BoardLayout.Media:
						return <AlbumListLayout boardListMeta={_board.boardMeta.list} speaker={speaker} notice={notice} list={list} startIndex={startIndex} onChange={setBoardPrefixID} />;
					case BoardLayout.QnA:
						return <QnAListLayout boardListMeta={_board.boardMeta.list} notice={notice} list={list} startIndex={startIndex} onChange={setBoardPrefixID} />;
					default:
						return <DefaultListLayout boardListMeta={_board.boardMeta.list} speaker={speaker} notice={notice} list={list} startIndex={startIndex} onChange={setBoardPrefixID} />;
				}
            })()}

			{/* 검색 */}
			<div className='list-footer'>
				<section aria-label='게시글 검색'>
					<form onSubmit={handleSearch} autoComplete='off'>
						<select name='search' value={search ?? ''} title='검색 구분' onChange={handleChange}>
							<option value={PostSearchType.Subject}>제목</option>
							<option value={PostSearchType.Content}>내용</option>
							<option value={PostSearchType.Author}>작성자</option>
							<option value={PostSearchType.Comment}>댓글</option>
						</select>
						<input type='text' name='keyword' value={keyword} placeholder='검색어를 입력해주세요.' onChange={handleChange} />
						<button type='submit' className='btn btn-default'>검색</button>
					</form>
				</section>

				{/* 글쓰기 버튼 */}
				<PostWriteButtonfrom alwaysShowButton={_board.boardMeta.list.alwaysShowWriteButton} boardCode={_board.code} />
			</div>

			<Pagination total={total} page={page} perPage={perPage} onChange={handlePageChange} />

			<FooterContent isEnabled={_board.boardMeta.list.showFooter} content={_board.boardMeta.list.footerContent } />
		</div>
	);
}